#include <keypad.h>
#include <Wire.h>
#include <LCDI2C4Bit.h>
#include <DS1307.h>
#include <avr/pgmspace.h>

#define ROWS 4
#define COLS 3

keypad kpd = keypad(ROWS, COLS);


int rtc[7];
char buf[5]; // "-2147483648\0"
int ADDR = 0x38;
byte rtcram[5];

/*
;Connect the following pins from MCP23008 to LCD
 ;
 ;P0 - D4
 ;P1 - D5
 ;P2 - D6
 ;P3 - D7
 ;P4 - RS
 ;P5 - RW (not used, set to 0 to ground for write)
 ;P6 - Bl (backlight switch)
 ;P7 - E1;Connect the following pins from MCP23008 to LCD
 */

byte x = 0;
byte data = 1;
byte c;

LCDI2C4Bit lcd = LCDI2C4Bit(ADDR,2,40);


//                             "0123456789ABCDEF"
prog_char string_0[] PROGMEM = "The Time Is     ";   // "String 0" etc are strings to store - change to suit.
prog_char string_1[] PROGMEM = "Set The Time ";
prog_char string_2[] PROGMEM = "String 2";
prog_char string_3[] PROGMEM = "String 3";
prog_char string_4[] PROGMEM = "String 4";
prog_char string_5[] PROGMEM = "String 5";


// Then set up a table to refer to your strings.

PGM_P string_table[] PROGMEM =	   // change "string_table" name to suit
{   
  string_0,
  string_1,
  string_2,
  string_3,
  string_4,
  string_5 };

char lcdbuffer1[17]= "0123456789ABCDEF";    // make sure this is large enough for the largest string it must hold
char lcdbuffer2[17]= "0123456789ABCDEF";    // lcd display buffer

//char* lcdbuffer[]={"0123456789ABCDEF", "0123456789ABCDEF"};

char* lcdbuffer[]= {
  lcdbuffer1,
  lcdbuffer2
  };






void setup()
{
  Serial.begin(9600);
  Wire.begin(); // join i2c bus (address optional for master)
  lcd.init();
  lcd.commandWrite(0x0F);
  //lcd.printIn("arnon");
  //WriteLCD(ADDR,'a');
  //LCDClear(ADDR);
  //WriteLCD(ADDR,'c');
  /* 
  lcd.cursorTo(1,0);
  lcd.printIn("1");
  lcd.cursorTo(2,0);
  lcd.printIn("2");
  lcd.cursorTo(3,0);
  lcd.printIn("3");
  */
  
  /*
  RTC.stop();
  RTC.set(DS1307_SEC,00);
  RTC.set(DS1307_MIN,30);
  RTC.set(DS1307_HR,15);
  RTC.set(DS1307_DOW,6);
  RTC.set(DS1307_DATE,5);
  RTC.set(DS1307_MTH,12);
  RTC.set(DS1307_YR,8);
  RTC.start();
  */
  strcpy_P(lcdbuffer[0], (char*)pgm_read_word(&(string_table[0]))); // Necessary casts and dereferencing, just copy. 
  Serial.println( lcdbuffer[0] );

  lcd.printIn(lcdbuffer[0]);
  
  kpd.init();
  digitalWrite(6, HIGH);
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);
  digitalWrite(9, HIGH);
  Time();
}


void loop()
{
  Time();
   char key = kpd.get_key();
   if(key == '*') //Yes
   {
    lcd.cursorTo(0,0);
    strcpy_P(lcdbuffer[0], (char*)pgm_read_word(&(string_table[1]))); // Necessary casts and dereferencing, just copy. 
    lcd.printIn(lcdbuffer[0]);
    
    
    settime(1,0);
    savetime(1,0);
    setdate();
    setdow();
    
    
    lcd.cursorTo(0,0);
      strcpy_P(lcdbuffer[0], (char*)pgm_read_word(&(string_table[0]))); // Necessary casts and dereferencing, just copy. 
    lcd.printIn(lcdbuffer[0]);
    
   }
   else if(key == '#') //No
   {
    lcd.cursorTo(0,0);
    strcpy_P(lcdbuffer[0], (char*)pgm_read_word(&(string_table[2]))); // Necessary casts and dereferencing, just copy. 
    lcd.printIn(lcdbuffer[0]);
    
     
     rtcread(0x08);
     //printnum(rtcram[3],1,0);
     printnum(B11111111,1,0);
     Serial.println("setonoff");
     setonoff(3,1,0);
     rtcwrite(0x08);
     
   }
     else if(key == '0')
   {
    lcd.cursorTo(0,0);
    strcpy_P(lcdbuffer[0], (char*)pgm_read_word(&(string_table[3]))); // Necessary casts and dereferencing, just copy. 
    lcd.printIn(lcdbuffer[0]);
    int i;
    Serial.println("rtcread");
    for (i = 0 ; i<10 ;i++){
    rtcread(i*5);
    
    }
   }
}

void printnum(byte byt  ,int line_num, int x){
  //Serial.print(x);
  Serial.print(byt);
  //char str[9]= "12345678" ;
  int i;
  for (i = 0 ; i < 8 ;i++){
    if (byt & (1<<i)){
      lcdbuffer[line_num][x+i] = 49 + i;  //Turn into ascii and 1 to 8
      //Serial.println("on");
      //Serial.println(i);
    }
    else
    {
      lcdbuffer[line_num][x+i]=' ';
      //Serial.println("off");
      //Serial.println(i);
    }
    //Serial.println(lcdbuffer[line_num][x+i]);
  }
  refresh(0);
  //return str;
}


void setonoff(int i, int line_num, int x){
  while(1){
    char key = kpd.get_key();
    if (key >= '1' && key <= '8'){
      
       rtcram[i] ^= (1 << (cTI(key)));
       
       
      //rtcram[i];
       printnum(rtcram[i],line_num,x);
    }
    else if (key == '0')
    {
      return;
      
      
    }
    
    
  }

  
  
}


void rtcread(int addr){
  Wire.beginTransmission(DS1307_CTRL_ID);
  Wire.send(addr);
  Wire.endTransmission();
  Wire.requestFrom(DS1307_CTRL_ID, 5);
  for(int i=0; i<5; i++)
  {
    // store data in raw bcd format
    rtcram[i]=Wire.receive();
    Serial.print(rtcram[i]);
  }
}



void rtcwrite(int addr){
  Wire.beginTransmission(DS1307_CTRL_ID);
  Wire.send(addr); // reset register pointer
  for(int i=0; i<5; i++)
  {
    Wire.send(rtcram[i]);
  }
  Wire.endTransmission();
}

void settime(int line_num, int x)
{
      char key = kpd.get_key();
      
      lcd.cursorTo(line_num,x);
      lcd.commandWrite(0x0D);
      lcd.cursorTo(line_num,x);
      
    //if(key != '\0')
    //{
      refresh(x);
      while(1){
        key = kpd.get_key();
      if (key >= '0' && key <= '2')
        {
          
        lcdbuffer[line_num][x] = (key);
        lcdbuffer[line_num][x+1] = ('0');
        
        refresh(x);
        //delay(200);     //debounce ?????
        lcd.cursorTo(line_num,x+1);
        //Serial.print('1');
        break;
        }
      }
        while(1){ // Hours
          key = kpd.get_key();
          if (key >= '1' && key <= '3')
          {
          lcdbuffer[line_num][x+1] = (key);
          refresh(x+3);
          break;
          }
          else if (key == '0')
          {
            if (lcdbuffer[line_num][x+0] == '1' || lcdbuffer[line_num][x+0] == '2')
            {
              lcdbuffer[line_num][x+1] = (key);
              refresh(x+3);
              break;

            
            }
          }
          else if (key >= '4' && key <= '9')
          {
            if (lcdbuffer[line_num][x+0] != '2')
            {
              lcdbuffer[line_num][x+1] = (key);
              refresh(x+3);
              break;

            
            }
            
          }
        }
          

          while(1){ // minutes
          key = kpd.get_key();
          if (key >= '0' && key <= '5')
          {
            lcdbuffer[line_num][x+3] = (key);
            refresh(x+4);
            break;
          }
            
          }
          //Serial.println("qq");
          //Serial.println(key);
          
          while(1){ // minutes 
          key = kpd.get_key();
          
          if (key >= '0' && key <= '9')
          {
          lcdbuffer[line_num][x+4] = (key);
          refresh(x+6);
          break;
          Serial.println(key);
          }
          }
          

        //char * thisChar = "A";
        //int a = atoi(lcdbuffer[1][12]); 
        
        Serial.println(key);
        refresh(x+0);
    //}   
    
    //Serial.println(key);

}


void savetime(int line_num, int x)
{
        RTC.get(rtc,true);
        RTC.stop();
        RTC.set(DS1307_SEC,00);
        RTC.set(DS1307_MIN,cTI(lcdbuffer[line_num][x+3])*10 + cTI(lcdbuffer[line_num][x+4]));
        RTC.set(DS1307_HR,cTI(lcdbuffer[line_num][x+0])*10 + cTI(lcdbuffer[line_num][x+1]));
        RTC.start();
}


void setdate()
{
      char key = kpd.get_key();
      lcd.cursorTo(1,0);
      lcd.commandWrite(0x0D);
      lcd.cursorTo(1,0);
    //if(key != '\0')
    //{
      
          refresh(6);

          
          while(1){ // days   tens
          key = kpd.get_key();
          
          if (key >= '0' && key <= '3')
          {
            lcdbuffer[1][6] = (key);
            refresh(7);
            break;
            Serial.println(key);
          }
          }
          
          while(1){ // days
            key = kpd.get_key();
            if (key == '1')
            {
              lcdbuffer[1][7] = (key);
              refresh(9);
              break;
              Serial.println(key);
            }
             else if (key >= '2' && key <= '9')
           {
            if (lcdbuffer[1][6] != '3')
            {
              lcdbuffer[1][7] = (key);
              refresh(9);
              break;
            }
           }
          else if (key == '0')
          {
            if (lcdbuffer[1][6] != '0' )
            {
              lcdbuffer[1][7] = (key);
              refresh(9);
              break;

            
            }
          }
          
          }
          
          
          
          
          while(1){ // months  tens
          key = kpd.get_key();
          if (key >= '0' && key <= '1')
          {
          lcdbuffer[1][9] = (key);
          refresh(10);
          break;
          Serial.println(key);
          }
            
          }
          
          while(1){ // months
            key = kpd.get_key();
            if (key == '1' || key == '2')
            {
              lcdbuffer[1][10] = (key);
              refresh(12);
              break;
              Serial.println(key);
            }
             else if (key >= '3' && key <= '9')
           {
            if (lcdbuffer[1][9] != '1')
            {
              lcdbuffer[1][10] = (key);
              refresh(12);
              break;
            }
           }
          else if (key == '0')
          {
            if (lcdbuffer[1][9] == '1' || lcdbuffer[1][9] == '2')
            {
              lcdbuffer[1][10] = (key);
              refresh(12);
              break;

            
            }
          }
         
          }
          
          
          while(1){ // years ten 
          key = kpd.get_key();
          
          if (key >= '0' && key <= '9')
          {
          lcdbuffer[1][12] = (key);
          refresh(13);
          break;
          Serial.println(key);
          }
          }
          
          while(1){ // years 
          key = kpd.get_key();
          
          if (key >= '0' && key <= '9')
          {
          lcdbuffer[1][13] = (key);
          refresh(0);
          break;
          Serial.println(key);
          }
          }

        //char * thisChar = "A";
        //int a = atoi(lcdbuffer[1][12]); 
        RTC.get(rtc,true);
        
        RTC.stop();
        
        RTC.set(DS1307_DATE,cTI(lcdbuffer[1][6])*10 + cTI(lcdbuffer[1][7]));
        RTC.set(DS1307_MTH,cTI(lcdbuffer[1][9])*10 + cTI(lcdbuffer[1][10]));
        Serial.print("set year");
        Serial.print(00);
        Serial.print(00);
        Serial.print(lcdbuffer[1][12]);
        Serial.print(00);
        Serial.print(00);
        Serial.print(cTI(lcdbuffer[1][12]));
        Serial.print(00);
        Serial.print(00);
        Serial.print(lcdbuffer[1][13]);
        Serial.print(00);
        Serial.print(00);
        Serial.print(cTI(lcdbuffer[1][13]));
        Serial.print(00);
        Serial.print(00);
        RTC.set(DS1307_YR,cTI(lcdbuffer[1][12])*10 + cTI(lcdbuffer[1][13]));
        RTC.start(); 
        
        Serial.println(key);
        refresh(0);
    //}   
    
    //Serial.println(key);

}


void setdow()
{
          refresh(15);
          char key = kpd.get_key();
          while(1){
            key = kpd.get_key();
            if (key >= '1' && key <= '7')
            {
              lcdbuffer[1][15] = (key);
              break;
            }
          }
          
          RTC.get(rtc,true);
          RTC.stop();
          RTC.set(DS1307_DOW,cTI(lcdbuffer[1][15]));
          RTC.start();
          
          refresh(0);
  
  
}








void Time()
{
  //delay(1000);
  RTC.get(rtc,true);
  
  lcd.cursorTo(1,0);
  lcd.commandWrite(0x0D);
  /*
    for(int i=0; i<7; i++)
  {
    Serial.print(rtc[i]);
    Serial.print(" ");
  }
  */
  /*
  for (int i = 0; i < 16; i++){
   lcdbuffer[1][i] = 'Q';
   }
  */
  
  //filllcd(itoa(rtc[DS1307_HR], buf , 10),0);
  filllcd(itoa(rtc[DS1307_HR], buf , 10),0);
  lcdbuffer[1][2] = (':');
  filllcd(itoa(rtc[DS1307_MIN], buf , 10),3);
  //lcdbuffer[1][5] = (':');
  //filllcd(itoa(rtc[DS1307_SEC], buf , 10),6);
  
  //Serial.println(lcdbuffer[1]);
  //Serial.println('n');
  
  lcdbuffer[1][5] =(' ');
  
  //Serial.println(lcdbuffer[1]);
  //Serial.println('b');
  
  
  filllcd(itoa(rtc[DS1307_DATE], buf , 10),6);
  
  //Serial.println(lcdbuffer[1]);
  //Serial.println('v');
  
  lcdbuffer[1][8] =('/');
  filllcd(itoa(rtc[DS1307_MTH], buf , 10),9);
  lcdbuffer[1][11] =(' ');
  filllcd(itoa(rtc[DS1307_YR], buf , 10),12);
  lcdbuffer[1][14] =(' ');
  
  //filllcd(itoa(rtc[DS1307_DOW], buf , 10),15);
  lcdbuffer[1][15] = itoa(rtc[DS1307_DOW], buf , 10)[0];
  //Serial.println(lcdbuffer[1]);
  //Serial.println('c');
  
  Serial.println("Time print");
  Serial.println(lcdbuffer[1]);                            //debug
  
  
  
  //Serial.println(lcdbuffer3);
  
  

    
    
    lcd.printIn(lcdbuffer[1]);
    //lcd.printIn(lcdbuffer3);
    
    //Serial.println(availableMemory());
}
      











void filllcd (char * date , int i){
  //Serial.println(i);
  if (date[1] == '\0'){
  lcdbuffer[1][i]= '0';
  lcdbuffer[1][i+1]= date[0];
  }
  else if (date[2] == '\0')
  {
  lcdbuffer[1][i]= date[0];
  lcdbuffer[1][i+1]= date[1];
  }
  else if (date[5] == '\0')
    {
  lcdbuffer[1][i]= date[0];
  lcdbuffer[1][i+1]= date[1];
  lcdbuffer[1][i+2]= date[2];
  lcdbuffer[1][i+3]= date[3];
  }
  //Serial.print(lcdbuffer[1][i]);
  //Serial.print(lcdbuffer[1][i+1]);
}



void refresh(int i){
  lcd.cursorTo(1,0);
  Serial.println("Refresh");
  Serial.println(lcdbuffer[1]);
  lcd.printIn(lcdbuffer[1]);
  
  lcd.cursorTo(1,i);
  lcd.commandWrite(0x0D);
  }



int availableMemory() {
  int size = 1024;
  byte *buf;

  while ((buf = (byte *) malloc(--size)) == NULL)
    ;

  free(buf);

  return size;
}




int cTI (char i){
return i - '0';
}


/*

int cTI (char i){ //CHANGES FROM CHAR TO INT
 if(i == '0'){
   return 0;
 }
 else if(i == '1'){
   return 1;
 }
 else if(i == '2'){
   return 2;
 }
 else if(i == '3'){
   return 3;
 }
 else if(i == '4'){
   return 4;
 }
 else if(i == '5'){
   return 5;
 }
 else if(i == '6'){
   return 6;
 }
 else if(i == '7'){
   return 7;
 }
 else if(i == '8'){
   return 8;
 }
 else if(i == '9'){
   return 9;
 }
 return 0;
}

*/
